package com.ebraga.trackerclub.android.util.core;

import android.database.Cursor;

import com.ebraga.trackerclub.android.exception.BackofficeDBConnectionException;
import com.ebraga.trackerclub.android.exception.dao.BackofficeDaoException;
import com.ebraga.trackerclub.android.exception.dao.BackofficeIllegalArgumentDaoException;
import com.ebraga.trackerclub.android.util.DLog;
import com.ebraga.trackerclub.android.util.api.AndroidContext;
import com.ebraga.trackerclub.android.util.api.AndroidSQLiteDatabase;
import com.ebraga.trackerclub.android.util.api.DataAccessObject;

public class DataAccessObjectImpl implements DataAccessObject {

	// Not available from static methods!
	protected final String TAG = this.getClass().toString();

	protected DatabaseHelper dbHelper;
	protected AndroidSQLiteDatabase db;
	protected Cursor c;

	protected AndroidContext context;

	protected String tableName = "";

    // Default query for entity (e.g. for use in list - filled in the entity constructor)
	protected String[] select;
	protected String where;
	protected String[] whereArgs; 
	protected String orderBy;
	// Values to store, display and filter on
	protected String valueColumn;
	protected String displayValueColumn;
	protected String dependentValueColumn;

	public DataAccessObjectImpl(AndroidContext context) {
		this.context = context;
		if (null == dbHelper) {
			dbHelper = new DatabaseHelper(context);
		}
		this.db = dbHelper.getAndroidWritableDatabase();
	}
	
	public AndroidSQLiteDatabase getDB() {
		if (null == db) {
			if (null == dbHelper) {
				//dbHelper = new DatabaseHelper(context);
			}
			db = dbHelper.getAndroidWritableDatabase();
		}
		return db;
	}

	/**
	 * Delete record in DB
	 * 
	 * @param id: sys_id from Service-now, not auto generated _id
	 */
	public void deleteRecord(String id) {
		getDB().delete(tableName, "id = '" + id + "'", null);
	}

	/**
	 * Delete all records in table
	 */
	public void deleteAllRecords() {
		getDB().delete(tableName, null, null);
	}

	/**
	 * Close cursor and database
	 * 
	 * Call after every usage of a dao!
	 */
	public void closeDB() {
		DLog.d(TAG, "Closing cursor and database");

		if (null != c && !c.isClosed()) {
			c.close();
		}
		if (null != db && db.isOpen()) {
			db.close();
		}
	}

	/**
	 * Get the standard cursor to create a ui list of entities. 
	 * E.g. all the active ones. 
	 * 
	 * @return Cursor
	 */
	public Cursor getCursor() {
		// Query the database
		try {
			return c = getDB().query(tableName, select, where, whereArgs, null, null, orderBy);
		} catch (BackofficeDBConnectionException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDaoException e) {
			e.printStackTrace();
			return null;
		}
	}

	public Cursor getCursor(String rawQuery) {
		// Query the database
		return getDB().rawQuery(rawQuery, null);
	}

	public Cursor getCursor(String tableName, String[] select, String where, String[] whereArgs, String orderBy) {
		// Query the database
		try {
			return c = getDB().query(tableName, select, where, whereArgs, null, null, orderBy);
		} catch (BackofficeIllegalArgumentDaoException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDBConnectionException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDaoException e) {
			e.printStackTrace();
			return null;
		}
	}

	public Cursor getCursorByDependentValue(String dependent) {
		// Query the database
		try {
			return c = getDB().query(tableName, select, dependentValueColumn + "=? AND active=?", new String[] {dependent, "1"}, null, null, orderBy);
		} catch (BackofficeIllegalArgumentDaoException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDBConnectionException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDaoException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * @param searchString
	 * @return all records where the column contains (LIKE) the search string
	 */
	public Cursor getCursorSearch(String column, String searchString) {
		// Query the database
		try {
			return c = getDB().query(tableName, select, column + " LIKE ?", new String[] {"%" + searchString + "%"}, null, null, orderBy);
		} catch (BackofficeIllegalArgumentDaoException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDBConnectionException e) {
			e.printStackTrace();
			return null;
		} catch (BackofficeDaoException e) {
			e.printStackTrace();
			return null;
		}
	}

    @Override
    protected void finalize() throws Throwable {
        closeDB();
    	super.finalize();
    }

	public String getTableName() {
		return this.tableName;
	}

	/**
	 * Get auto incremented _id based on sys_id
	 * 
	 * @param id
	 * @return
	 */
	public long getRowId(String id) {
		try {
			c = getDB().query(tableName, new String[] {"_id"}, "id=?", new String[] {id}, null, null, null);
		} catch (BackofficeIllegalArgumentDaoException e) {
			e.printStackTrace();
		} catch (BackofficeDBConnectionException e) {
			e.printStackTrace();
		} catch (BackofficeDaoException e) {
			e.printStackTrace();
		}

		c.moveToFirst();
		int result = c.getInt(c.getColumnIndex("_id"));
		c.close();

		return result;
	}

	// TODO: Is this really faster than BusinessServiceDAO.getInstance().getRecord(incident.getBs()).getDisplayValue() ? + it doesn't work for choices
	/**
	 * @return contents of user readable column
	 * @param id: sys_id from Service-now, not auto generated _id
	 */
	public String getDisplayValue(String id) {
		String result = "";

		if (null != id) {
			try {
				c = getDB().query(tableName, new String[] {displayValueColumn}, "id=?", new String[] {id}, null, null, null);
			} catch (BackofficeIllegalArgumentDaoException e) {
				e.printStackTrace();
			} catch (BackofficeDBConnectionException e) {
				e.printStackTrace();
			} catch (BackofficeDaoException e) {
				e.printStackTrace();
			}

			if (c.moveToFirst()) {
				result = c.getString(c.getColumnIndexOrThrow(displayValueColumn));
			}

			c.close();
		}

		return result;
	}
	/**
	 * @return name of column that holds key
	 */
	public String getValueColumn() {
		return valueColumn;
	}
	/**
	 * @return name of user readable column
	 */
	public String getDisplayValueColumn() {
		return displayValueColumn;
	}
	/**
	 * @return name of column that is used to filter results
	 */
	public String getDependentValueColumn() {
		return dependentValueColumn;
	}


}
